package com.easychat.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import com.easychat.entity.dto.MessageSendDTO;
import com.easychat.entity.dto.SysSettingDTO;
import com.easychat.entity.enums.*;
import com.easychat.entity.po.*;
import com.easychat.entity.query.*;
import com.easychat.exception.BusinessException;
import com.easychat.mappers.*;
import com.easychat.redis.RedisComponent;
import com.easychat.websocket.ChannelContextUtils;
import com.easychat.websocket.MessageHandler;
import org.apache.catalina.User;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import com.easychat.entity.vo.PaginationResultVO;
import com.easychat.service.UserContactApplyService;
import com.easychat.utils.StringTools;
import org.springframework.transaction.annotation.Transactional;


/**
 * 申请信息 业务接口实现
 */
@Service("userContactApplyService")
public class UserContactApplyServiceImpl implements UserContactApplyService {

	@Resource
	private UserContactApplyMapper<UserContactApply, UserContactApplyQuery> userContactApplyMapper;
	@Resource
	private UserContactMapper<UserContact, UserContactQuery> userContactMapper;
	@Resource
	private UserInfoMapper<UserInfo, UserInfoQuery> userInfoMapper;
	@Resource
	private GroupInfoMapper<GroupInfo, GroupInfoQuery> groupInfoMapper;
	@Resource
	private ChatSessionMapper<ChatSession, ChatSessionQuery> chatSessionMapper;
	@Resource
	private ChatSessionUserMapper<ChatSessionUser, ChatSessionUserQuery> chatSessionUserMapper;
	@Resource
	private ChatMessageMapper<ChatMessage, ChatMessageQuery> chatMessageMapper;
	@Resource
	private MessageHandler messageHandler;
	@Resource
	private ChannelContextUtils channelContextUtils;
	@Resource
	private RedisComponent redisComponent;

	/**
	 * 根据条件查询列表
	 */
	@Override
	public List<UserContactApply> findListByParam(UserContactApplyQuery param) {
		return this.userContactApplyMapper.selectList(param);
	}

	/**
	 * 根据条件查询列表
	 */
	@Override
	public Integer findCountByParam(UserContactApplyQuery param) {
		return this.userContactApplyMapper.selectCount(param);
	}

	/**
	 * 分页查询方法
	 */
	@Override
	public PaginationResultVO<UserContactApply> findListByPage(UserContactApplyQuery param) {
		int count = this.findCountByParam(param);
		int pageSize = param.getPageSize() == null ? PageSize.SIZE15.getSize() : param.getPageSize();

		SimplePage page = new SimplePage(param.getPageNo(), count, pageSize);
		param.setSimplePage(page);
		List<UserContactApply> list = this.findListByParam(param);
		PaginationResultVO<UserContactApply> result = new PaginationResultVO(count, page.getPageSize(), page.getPageNo(), page.getPageTotal(), list);
		return result;
	}

	/**
	 * 新增
	 */
	@Override
	public Integer add(UserContactApply bean) {
		return this.userContactApplyMapper.insert(bean);
	}

	/**
	 * 批量新增
	 */
	@Override
	public Integer addBatch(List<UserContactApply> listBean) {
		if (listBean == null || listBean.isEmpty()) {
			return 0;
		}
		return this.userContactApplyMapper.insertBatch(listBean);
	}

	/**
	 * 批量新增或者修改
	 */
	@Override
	public Integer addOrUpdateBatch(List<UserContactApply> listBean) {
		if (listBean == null || listBean.isEmpty()) {
			return 0;
		}
		return this.userContactApplyMapper.insertOrUpdateBatch(listBean);
	}

	/**
	 * 多条件更新
	 */
	@Override
	public Integer updateByParam(UserContactApply bean, UserContactApplyQuery param) {
		StringTools.checkParam(param);
		return this.userContactApplyMapper.updateByParam(bean, param);
	}

	/**
	 * 多条件删除
	 */
	@Override
	public Integer deleteByParam(UserContactApplyQuery param) {
		StringTools.checkParam(param);
		return this.userContactApplyMapper.deleteByParam(param);
	}

	/**
	 * 根据ApplyId获取对象
	 */
	@Override
	public UserContactApply getUserContactApplyByApplyId(Integer applyId) {
		return this.userContactApplyMapper.selectByApplyId(applyId);
	}

	/**
	 * 根据ApplyId修改
	 */
	@Override
	public Integer updateUserContactApplyByApplyId(UserContactApply bean, Integer applyId) {
		return this.userContactApplyMapper.updateByApplyId(bean, applyId);
	}

	/**
	 * 根据ApplyId删除
	 */
	@Override
	public Integer deleteUserContactApplyByApplyId(Integer applyId) {
		return this.userContactApplyMapper.deleteByApplyId(applyId);
	}

	/**
	 * 根据ApplyUserIdAndReceiveUserIdAndContactId获取对象
	 */
	@Override
	public UserContactApply getUserContactApplyByApplyUserIdAndReceiveUserIdAndContactId(String applyUserId, String receiveUserId, String contactId) {
		return this.userContactApplyMapper.selectByApplyUserIdAndReceiveUserIdAndContactId(applyUserId, receiveUserId, contactId);
	}

	/**
	 * 根据ApplyUserIdAndReceiveUserIdAndContactId修改
	 */
	@Override
	public Integer updateUserContactApplyByApplyUserIdAndReceiveUserIdAndContactId(UserContactApply bean, String applyUserId, String receiveUserId, String contactId) {
		return this.userContactApplyMapper.updateByApplyUserIdAndReceiveUserIdAndContactId(bean, applyUserId, receiveUserId, contactId);
	}

	/**
	 * 根据ApplyUserIdAndReceiveUserIdAndContactId删除
	 */
	@Override
	public Integer deleteUserContactApplyByApplyUserIdAndReceiveUserIdAndContactId(String applyUserId, String receiveUserId, String contactId) {
		return this.userContactApplyMapper.deleteByApplyUserIdAndReceiveUserIdAndContactId(applyUserId, receiveUserId, contactId);
	}

	/**
	 * 处理联系人申请
	 * @param receiveUserId 接收人id
	 * @param applyId 申请的id(对应自增id)
	 * @param status 申请状态 已同意、已拒绝、拉黑
	 * @return
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void dealWithApply(String receiveUserId, Integer applyId, Integer status) {
		//通过status获取对应的枚举
		UserContactApplyStatusEnum userContactApplyStatusEnum = UserContactApplyStatusEnum.getByStatus(status);
		if (userContactApplyStatusEnum == null || status.equals(UserContactApplyStatusEnum.PENDING.getStatus())) {
			//传入的status没有对应的枚举 || 传入的status对应待处理PENDING，参数错误
			throw new BusinessException(ResponseCodeEnum.CODE_600);
		}
		//通过applyId查询申请信息
		UserContactApply dbContactApply = userContactApplyMapper.selectByApplyId(applyId);
		if (dbContactApply == null || !dbContactApply.getReceiveUserId().equals(receiveUserId)) {
			//是接收者才能处理自己的申请信息
			throw new BusinessException(ResponseCodeEnum.CODE_600);
		}
		//更新后的值 set...
		UserContactApply updateApply = new UserContactApply();
		updateApply.setStatus(status);
		updateApply.setLastApplyTime(System.currentTimeMillis());
		//更新时的条件 where...
		UserContactApplyQuery userContactApplyQuery = new UserContactApplyQuery();
		userContactApplyQuery.setApplyId(applyId);
		userContactApplyQuery.setStatus(UserContactApplyStatusEnum.PENDING.getStatus());
		//TODO update user_contact_apply set status = 1, last_apply_time = now() where apply_id = ? and status = 0
		//TODO 只能由初始状态0变为其他状态1，2，3
		//TODO 只有这部分是不对的：update user_contact_apply set status = 1, last_apply_time = now() where apply_id = ?
		//TODO status 0->1 1->3 3->2 不行
		Integer count = userContactApplyMapper.updateByParam(updateApply, userContactApplyQuery);
		if (count == 0) {
			throw new BusinessException(ResponseCodeEnum.CODE_600);
		}
		//不同状态的处理
		if (UserContactApplyStatusEnum.ALLOWED.getStatus().equals(status)) {
			//TODO 添加联系人
			addContact(dbContactApply);
			return;
		}
		if (UserContactApplyStatusEnum.BLACKLIST.getStatus().equals(status)) {
			//更新user_contact表
			Date curDate = new Date();
			UserContact userContact = new UserContact();
			userContact.setUserId(dbContactApply.getApplyUserId());
			userContact.setContactId(dbContactApply.getContactId());
			userContact.setContactType(dbContactApply.getContactType());
			//注意：这里状态为被拉黑，因为userId对应申请人
			userContact.setStatus(UserContactStatusEnum.BLACKLIST_BY_FIRST.getStatus());
			userContact.setLastUpdateTime(curDate);
			userContact.setCreateTime(curDate);
			userContactMapper.insertOrUpdate(userContact);
			return;
		}

	}

	/**
	 * 添加联系人
	 * @param userContactApply
	 */
	@Override
	public void addContact(UserContactApply userContactApply) {
		String applyUserId = userContactApply.getApplyUserId();
		String receiveUserId = userContactApply.getReceiveUserId();
		String contactId = userContactApply.getContactId();
		Integer contactType = userContactApply.getContactType();
		String applyInfo = userContactApply.getApplyInfo();
		//申请加群组的情况
		if (UserTypeEnum.GROUP.getType().equals(contactType)) {
			//看群人数是否超出限制
			UserContactQuery userContactQuery = new UserContactQuery();
			userContactQuery.setContactId(contactId);//指定群ID
			userContactQuery.setStatus(UserContactStatusEnum.FRIEND.getStatus());//指定状态为好友
			Integer groupMembers = userContactMapper.selectCount(userContactQuery);
			SysSettingDTO sysSetting = redisComponent.getSysSetting();
			if (groupMembers >= sysSetting.getMaxGroupMemberCount()) {
				throw new BusinessException("群人数超出限制，最大人数为" + sysSetting.getMaxGroupMemberCount());
			}
		}
		//双方添加好友：如果是人+人，需要向user_contact表添加两条数据，user_id和contact_id相反
		//如果是人+群，只需要向user_contact表添加一条数据
		Date curDate = new Date();
		List<UserContact> userContactList = new ArrayList<>();
		UserContact userContact = new UserContact();
		userContact.setUserId(applyUserId);
		userContact.setContactId(contactId);
		userContact.setContactType(contactType);
		userContact.setStatus(UserContactStatusEnum.FRIEND.getStatus());
		userContact.setCreateTime(curDate);
		userContact.setLastUpdateTime(curDate);
		userContactList.add(userContact);
		if (UserTypeEnum.USER.getType().equals(contactType)) {
			//人+人
			UserContact userContact2 = new UserContact();
			userContact2.setUserId(receiveUserId);
			userContact2.setContactId(applyUserId);
			userContact2.setContactType(contactType);
			userContact2.setStatus(UserContactStatusEnum.FRIEND.getStatus());
			userContact2.setCreateTime(curDate);
			userContact2.setLastUpdateTime(curDate);
			userContactList.add(userContact2);
		}
		//批量插入
		userContactMapper.insertOrUpdateBatch(userContactList);
		//如果是好友，接收人也添加申请人为好友 添加缓存
		//向redis缓存中添加联系人信息
		if (UserTypeEnum.USER.getType().equals(contactType)) {
			//人+人 额外加：对方添加自己为好友
			redisComponent.saveUserContact(receiveUserId, applyUserId);
		}
		//人+群，只需要添加群id的联系人信息
		redisComponent.saveUserContact(applyUserId, contactId);

		//创建会话 发送消息
		String sessionId = null;
		if (UserTypeEnum.USER.getType().equals(contactType)) {
			sessionId = StringTools.getChatSessionId4User(new String[]{applyUserId, contactId});
		} else if (UserTypeEnum.GROUP.getType().equals(contactType)) {
			sessionId = StringTools.getChatSessionId4Group(contactId);
		}
		List<ChatSessionUser> chatSessionUserList = new ArrayList<>();
		if (UserTypeEnum.USER.getType().equals(contactType)) {
			//会话信息 chat_session表
			ChatSession chatSession = new ChatSession();
			chatSession.setSessionId(sessionId);
			chatSession.setLastMessage(applyInfo);
			chatSession.setLastReceiveTime(curDate.getTime());
			chatSessionMapper.insertOrUpdate(chatSession);//当删除联系人后又再次添加时，需要更新而不是插入

			//会话人信息 chat_session_user表 申请人信息
			ChatSessionUser chatSessionUser = new ChatSessionUser();
			chatSessionUser.setSessionId(sessionId);
			chatSessionUser.setUserId(applyUserId);
			chatSessionUser.setContactId(contactId);
			UserInfo contactUserInfo = userInfoMapper.selectByUserId(contactId);
			chatSessionUser.setContactName(contactUserInfo.getNickName());
			chatSessionUserList.add(chatSessionUser);
			//会话人信息 chat_session_user表 接收人信息
			ChatSessionUser contactChatSessionUser = new ChatSessionUser();
			contactChatSessionUser.setSessionId(sessionId);
			contactChatSessionUser.setUserId(contactId);
			contactChatSessionUser.setContactId(applyUserId);
			UserInfo applyUserInfo = userInfoMapper.selectByUserId(applyUserId);
			contactChatSessionUser.setContactName(applyUserInfo.getNickName());
			chatSessionUserList.add(contactChatSessionUser);
			chatSessionUserMapper.insertOrUpdateBatch(chatSessionUserList);

			//记录消息，chat_message表
			ChatMessage chatMessage = new ChatMessage();
			chatMessage.setSessionId(sessionId);
			chatMessage.setMessageType(MessageTypeEnum.ADD_FRIEND.getType());
			chatMessage.setMessageContent(applyInfo);
			chatMessage.setSendUserId(applyUserId);
			chatMessage.setSendUserNickName(applyUserInfo.getNickName());
			chatMessage.setSendTime(curDate.getTime());
			chatMessage.setContactId(contactId);
			chatMessage.setContactType(UserTypeEnum.USER.getType());
			chatMessageMapper.insert(chatMessage);

			//发消息
			MessageSendDTO messageSendDTO = new MessageSendDTO();
			BeanUtils.copyProperties(chatMessage, messageSendDTO);
			messageHandler.sendMessage(messageSendDTO);//发消息给接收人
			//发消息给申请人，此时发送人和联系人反过来
			messageSendDTO.setMessageType(MessageTypeEnum.ADD_FRIEND_SELF.getType());
			messageSendDTO.setContactId(applyUserId);
			messageSendDTO.setExtendData(contactUserInfo);
			messageHandler.sendMessage(messageSendDTO);
		} else if (UserTypeEnum.GROUP.getType().equals(contactType)) {
			//加群
			//会话人信息 chat_session_user表 申请人信息
			ChatSessionUser chatSessionUser = new ChatSessionUser();
			chatSessionUser.setSessionId(sessionId);
			chatSessionUser.setUserId(applyUserId);
			chatSessionUser.setContactId(contactId);
			GroupInfo groupInfo = groupInfoMapper.selectByGroupId(contactId);
			chatSessionUser.setContactName(groupInfo.getGroupName());
			chatSessionUserMapper.insertOrUpdate(chatSessionUser);

			//xxx加入了群组
			UserInfo applyUserInfo = userInfoMapper.selectByUserId(applyUserId);
			String msg = String.format(MessageTypeEnum.ADD_GROUP.getInitMessage(), applyUserInfo.getNickName());

			//会话信息 chat_session表
			ChatSession chatSession = new ChatSession();
			chatSession.setSessionId(sessionId);
			chatSession.setLastMessage(msg);
			chatSession.setLastReceiveTime(curDate.getTime());
			chatSessionMapper.insertOrUpdate(chatSession);

			//增加聊天消息，chat_message表
			ChatMessage chatMessage = new ChatMessage();
			chatMessage.setSessionId(sessionId);
			chatMessage.setMessageType(MessageTypeEnum.ADD_GROUP.getType());
			chatMessage.setMessageContent(msg);
			chatMessage.setSendTime(curDate.getTime());
			chatMessage.setContactId(contactId);
			chatMessage.setContactType(UserTypeEnum.GROUP.getType());
			chatMessage.setStatus(MessageStatusEnum.COMPLETED.getStatus());
			chatMessageMapper.insert(chatMessage);

			//将申请人id对应的channel添加到groupId对应的channelGroup
			channelContextUtils.addUser2Group(applyUserId, contactId);

			//发送群消息
			MessageSendDTO messageSendDTO = new MessageSendDTO();
			BeanUtils.copyProperties(chatMessage, messageSendDTO);
			//获取群人数
			UserContactQuery userContactQuery = new UserContactQuery();
			userContactQuery.setContactId(contactId);
			userContactQuery.setStatus(UserContactStatusEnum.FRIEND.getStatus());
			Integer memberCount = userContactMapper.selectCount(userContactQuery);
			messageSendDTO.setMemberCount(memberCount);
			messageSendDTO.setContactName(groupInfo.getGroupName());
			//发消息
			messageHandler.sendMessage(messageSendDTO);
		}
	}
}